import React, { memo, useState, useEffect } from 'react'
import type { FC, ReactNode } from 'react'
import { Tabs, ConfigProvider } from 'antd'
import { v4 as uuidv4 } from 'uuid'

import CodeEditor from '../../Monacoeditor'
import LanguageSelector from '../LanguageSelector'

import { useMyDispatch, useMySelector, MyShallEqual } from '../../../store'
import {
  setCodeAll,
  setCodeChange,
  setLanguageChange
} from '../../../store/modules/codeall'
import { setCodeNum } from '../../../store/modules/create'
import { setFocusLanguage, setCopyCode } from '../../../store/modules/success'
import styles from './index.module.scss'

type TargetKey = React.MouseEvent | React.KeyboardEvent | string

interface CodeItem {
  key: string
  label: string
  codeSlice: string
  language: string
}

interface IProps {
  children?: ReactNode
}

const CodeSelector: FC<IProps> = () => {
  const dispatch = useMyDispatch()
  const {
    codeContent,
    successLanguage,
    codeAll,
    codeChange,
    languageChange,
    codeNum
  } = useMySelector(
    (state) => ({
      codeContent: state.success.codeContent,
      successLanguage: state.success.successLanguage,
      codeAll: state.codeall.codeAll,
      codeChange: state.codeall.codeChange,
      languageChange: state.codeall.languageChange,
      codeNum: state.code.codeNum
    }),
    MyShallEqual
  ) as {
    codeContent: string
    successLanguage: string
    codeAll: CodeItem[]
    codeChange: boolean
    languageChange: boolean
    codeNum: number
  }

  const initialItems =
    codeAll && codeAll.length > 0
      ? codeAll.map((item) => ({
          ...item,
          children: (
            <>
              <LanguageSelector language={item.language} />
              <CodeEditor code={item.codeSlice} />
            </>
          )
        }))
      : [
          {
            label: `代码 ${codeNum}`,
            key: `${uuidv4()}`,
            language: '',
            codeSlice: '',
            children: (
              <>
                <LanguageSelector />
                <CodeEditor />
              </>
            )
          }
        ]

  const [activeKey, setActiveKey] = useState(initialItems[0].key)
  const [items, setItems] = useState(initialItems)

  useEffect(() => {
    changeValue()
    console.log(codeAll)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dispatch, activeKey, codeChange, languageChange])

  const changeValue = () => {
    if (codeChange || languageChange) {
      const currentItem = items.find((item) => item.key === activeKey)
      if (currentItem && codeChange) currentItem.codeSlice = codeContent
      if (currentItem && languageChange) currentItem.language = successLanguage
      if (languageChange && currentItem && currentItem.key === items[0].key)
        dispatch(setFocusLanguage(successLanguage))
      if (codeChange && currentItem && currentItem.key === items[0].key)
        dispatch(setCopyCode(codeContent))
    }

    const itemall = items.map((item) => {
      const { children: _, ...rest } = item
      return rest
    })
    dispatch(setCodeAll(itemall))
    dispatch(setCodeChange(false))
    dispatch(setLanguageChange(false))
  }

  const onChange = (newActiveKey: string) => {
    changeValue()
    setActiveKey(newActiveKey)
  }

  const add = () => {
    const newPanes = [...items]
    newPanes.push({
      label: `代码 ${codeNum + 1}`,
      children: (
        <>
          <LanguageSelector />
          <CodeEditor />
        </>
      ),
      key: `${uuidv4()}`,
      language: '',
      codeSlice: ''
    })
    dispatch(setCodeNum(codeNum + 1))
    setItems(newPanes)
    // 注意高亮需要使用newPanes，react是异步的，setItems会慢一步
    setActiveKey(newPanes[newPanes.length - 1].key)
  }

  const remove = (targetKey: TargetKey) => {
    let newActiveKey = activeKey
    let lastIndex = -1
    items.forEach((item, i) => {
      if (item.key === targetKey) {
        lastIndex = i - 1
      }
    })
    const newPanes = items.filter((item) => item.key !== targetKey)
    if (newPanes.length && newActiveKey === targetKey) {
      if (lastIndex >= 0) {
        newActiveKey = newPanes[lastIndex].key
      } else {
        newActiveKey = newPanes[0].key
      }
    }
    setItems(newPanes)
    setActiveKey(newActiveKey)
  }
  const onEdit = (
    targetKey: React.MouseEvent | React.KeyboardEvent | string,
    action: 'add' | 'remove'
  ) => {
    if (action === 'add') {
      if (items.length >= 7) {
        alert('最多只能添加7个代码块')
        return
      }
      add()
    } else {
      if (items.length <= 1) {
        alert('至少需要一个代码块')
        return
      }
      remove(targetKey)
    }
    changeValue()
  }

  return (
    <ConfigProvider
      theme={{
        token: {
          colorPrimary: '#00b96b',
          colorText: '#fff',
          controlHeight: 20
        },
        components: {
          Tabs: {
            cardGutter: 8, // 调整卡片间距
            colorIcon: '#fff'
          }
        }
      }}
    >
      <Tabs
        type="editable-card"
        aria-disabled
        onChange={onChange}
        activeKey={activeKey}
        onEdit={onEdit}
        items={items}
        className={styles.codeselector}
      />
    </ConfigProvider>
  )
}

export default memo(CodeSelector)
